package com.say.utils;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.say.framework.core.util.SystemResourceLocator;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class RSAUtils {

	private static final Logger logger = LoggerFactory.getLogger(RSAUtils.class);

	//私钥
	public static String RSAPRIVATEKEY = (String) SystemResourceLocator.getValue("HTTP_RSAPRIVATEKEY");

	//公钥
	public static String RSAPUBLICKEY = (String) SystemResourceLocator.getValue("HTTP_RSAPUBLICKEY");
	
	/** 
	 * RSA公钥加密过程
	 * @param str 需要加密的明文字符串
	 * @return 加密后的密文字符串，加密异常返回null
	 */
	public static String encrypt(String str) {
		if (str == null) {
			logger.warn("对null进行加密");
			return null;
		}

		String encrypt = null;
		try {
			//base64编码的公钥
			byte[] decoded = Base64.decodeBase64(RSAPUBLICKEY);
			RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
			//RSA加密
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.ENCRYPT_MODE, pubKey);
			encrypt = Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
		} catch (Exception e) {
			logger.error("str=[{}]", str);
			logger.error("公钥加密异常", e);
		}
		return encrypt;
	}

	/** 
	 * RSA私钥解密过程
	 * @param str 需要解密的密文字符串
	 * @return 解密出的明文字符串，解密异常返回null
	 */
	public static String decrypt(String str) {
		if (str == null) {
			logger.warn("对null进行解密");
			return null;
		}

		String decrypt = null;
		try {
			//64位解码加密后的字符串
			byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
			//base64编码的私钥
			byte[] decoded = Base64.decodeBase64(RSAPRIVATEKEY);
			RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
			//RSA解密
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, priKey);
			decrypt = new String(cipher.doFinal(inputByte));
		} catch (Exception e) {
			logger.error("str=[{}]", str);
			logger.error("私钥解密异常", e);
		}
		return decrypt;
	}

	/**
	 * RSA私钥加密过程
	 * @param str 需要加密的明文字符串
	 * @return 加密后的密文字符串
	 */
	public static String encryptByPrivateKey(String str) throws Exception {
		//base64编码的私钥
		byte[] decoded = Base64.decodeBase64(RSAPRIVATEKEY);
		RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
	}

	/**
	 * RSA公钥解密过程
	 *
	 * @param str 需要解密的密文字符串
	 * @return 解密后的明文字符串
	 * @throws Exception 解密过程中的异常信息
	 */
	public static String decryptByPublicKey(String str) throws Exception {
		//base64编码的公钥
		//64位解码加密后的字符串
		byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
		byte[] decoded = Base64.decodeBase64(RSAPUBLICKEY);
		RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
		//RSA加密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		return new String(cipher.doFinal(inputByte));
	}


	/**
	 * 生成新的随机密钥对
	 *
	 * @throws NoSuchAlgorithmException 抛出异常
	 */
	public static Map<Integer, String> genKeyPair() throws NoSuchAlgorithmException {
		Map<Integer, String> keyMap = new HashMap<>();
		// KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象  
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
		// 初始化密钥对生成器，密钥大小为96-1024位  
		keyPairGen.initialize(1024, new SecureRandom());
		// 生成一个密钥对，保存在keyPair中  
		KeyPair keyPair = keyPairGen.generateKeyPair();
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥  
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥  
		String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
		// 得到私钥字符串  
		String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
		// 将公钥和私钥保存到Map
		keyMap.put(0, publicKeyString);  //0表示公钥
		keyMap.put(1, privateKeyString);  //1表示私钥
		return keyMap;
	}  
	
	
//	public static void main(String[] args) throws Exception {
//		// 生成公钥和私钥
//		// 加密字符串
//		String message = "111222";
//		String messageEn = RSAUtils.encrypt(message);
//		System.out.println(message + "\t加密后的字符串为:" + messageEn);
//		String messageDe = RSAUtils.decrypt("NB7Ufyzur4iRnuIHK7pwM0u6a2NFHMim/IM10c3oWoEMCM+zd4BrHKU1LMZ0x3m/sBgPi+tJzEU9npzhZgTLxsvhxJzZLK986hjwzrvvNlPjbTZJGPrH+d8YlUbd/ZcOQ0HtrM5l7RlR9UzyY8szHaCSXnh1NUX5nIvF9HXVegIrA=n");
//		System.out.println("还原后的字符串为:" + messageDe);
//		String messageEn1 = RSAUtils.encryptByPrivateKey(message);
//		System.out.println(message + "\t加密后的字符串为:" + messageEn1);
//		String messageDe1 = RSAUtils.decryptByPublicKey(messageEn1);
//		System.out.println("还原后的字符串为:" + messageDe1);
//	}

}

